// 控制选项卡切换
document.addEventListener('DOMContentLoaded', function () {
    // 初始化控制选项卡
    initControlTabs();
    // 初始化复选框
    initCheckbox();
    // 初始化单选按钮
    initRadioButtons();
    // 初始化WebSocket连接
    initWebSocket();
    // 添加初始日志
    addLog("系统初始化完成", "success");
    addLog("控制面板选项卡加载完成", "info");
    addLog("机械臂系统就绪", "success");

    // 新增：初始化点位数据、表格渲染、筛选事件
    renderPointData();       // 渲染表格
    initFilterEvents();      // 绑定搜索筛选事件
});

// 初始化控制选项卡
function initControlTabs() {
    const tabs = document.querySelectorAll('.control-tab');
    const tabContents = document.querySelectorAll('.control-tab-content');

    tabs.forEach(tab => {
        tab.addEventListener('click', function () {
            const tabId = this.getAttribute('data-tab');

            // 移除所有活动状态
            tabs.forEach(t => t.classList.remove('active'));
            tabContents.forEach(c => c.classList.remove('active'));

            // 添加当前活动状态
            this.classList.add('active');
            document.getElementById(`tab-${tabId}`).classList.add('active');

            addLog(`切换到${this.textContent}选项卡`, "info");
        });
    });
}

// 切换一级选项卡（数据展示区域）
function switchMainTab(tabName) {
    console.log('切换主选项卡:', tabName);

    // 隐藏所有二级选项卡容器
    document.querySelectorAll('[id^="sub-tabs-"]').forEach(tab => {
        tab.style.display = 'none';
    });

    // 隐藏所有内容区域 - 只针对右侧面板的tab-content
    document.querySelectorAll('.right-panel .tab-content').forEach(content => {
        content.classList.remove('active');
    });

    // 移除所有一级选项卡的活动状态
    document.querySelectorAll('.main-tab').forEach(tab => {
        tab.classList.remove('active');
    });

    // 激活当前一级选项卡
    const activeTab = document.querySelector(`.main-tab[onclick="switchMainTab('${tabName}')"]`);
    if (activeTab) {
        activeTab.classList.add('active');
    }

    // 显示对应的二级选项卡容器
    const subTabs = document.getElementById(`sub-tabs-${tabName}`);
    if (subTabs) {
        subTabs.style.display = 'flex';
    }

    // 显示对应内容区域的第一个子选项
    const firstSubTab = document.querySelector(`#sub-tabs-${tabName} .sub-tab`);
    if (firstSubTab) {
        const subTabName = firstSubTab.getAttribute('onclick').match(/'([^']+)'/g)[1].replace(/^'|'$/g, '');
        switchSubTab(tabName, subTabName);
    }
}

// 切换二级选项卡（数据展示区域）
function switchSubTab(mainTab, subTab) {
    console.log('切换子选项卡:', mainTab, subTab);

    // 移除当前主选项卡下所有二级选项卡的活动状态
    document.querySelectorAll(`#sub-tabs-${mainTab} .sub-tab`).forEach(tab => {
        tab.classList.remove('active');
    });

    // 隐藏当前主选项卡下所有内容区域 - 只针对右侧面板
    document.querySelectorAll(`.right-panel [id^="content-${mainTab}-"]`).forEach(content => {
        content.classList.remove('active');
    });

    // 激活当前二级选项卡
    const activeSubTab = document.querySelector(`#sub-tabs-${mainTab} .sub-tab[onclick="switchSubTab('${mainTab}', '${subTab}')"]`);
    if (activeSubTab) {
        activeSubTab.classList.add('active');
    }

    // 显示对应的内容区域
    const content = document.getElementById(`content-${mainTab}-${subTab}`);

    if (content) {
        content.classList.add('active');
    }
}

// 初始化单选框
function initRadioButtons() {
    const radioButtons = document.querySelectorAll('input[name="tieMode"]');

    radioButtons.forEach(radio => {
        radio.addEventListener('change', function () {
            if (this.checked) {
                const selectedValue = this.value;
                console.log('选择的绑扎模式:', selectedValue);
                callAPI('/api/cabin/setplum', 'POST', { "status": selectedValue });
            }
        });
    });
}
// 初始化选项框
function initCheckbox() {
    const armTieCheck = document.getElementById('armTieCheck');
    const armDiveCheck = document.getElementById('armDiveCheck');

    armTieCheck.addEventListener('change', function () {
        if (this.checked) {
            // 开关打开时执行的函数
            onArmTieIsEnabled(1);
        } else {
            // 开关关闭时执行的函数
            onArmTieIsEnabled(0);
        }
    });
    armDiveCheck.addEventListener('change', function () {
        if (this.checked) {
            // 开关打开时执行的函数
            onArmDiveIsEnabled(1);
        } else {
            // 开关关闭时执行的函数
            onArmDiveIsEnabled(0);
        }
    });
}
// 对应的处理函数
function onArmTieIsEnabled(action) {
    const actions = {
        0: "关闭绑扎",
        1: "开启绑扎",
    };
    addLog(`${actions[action]}...`, "info");
    callAPI('/api/arm/isShot', 'POST', { "status": action });
}

function onArmDiveIsEnabled(action) {
    const actions = {
        0: "关闭下潜",
        1: "开启下潜",
    };
    addLog(`${actions[action]}...`, "info");
    callAPI('/api/arm/isDown', 'POST', { "status": action });
}

// 节点控制函数
function controlRosNode(action) {
    const actions = {
        1: "启动所有节点",
        2: "重启所有节点",
        3: "关闭所有节点"
    };
    addLog(`${actions[action]}...`, "info");
    callAPI('/api/ros/status', 'POST', { "status": action });
}

// 索驱控制函数
function cableGlobalTie() {
    const tieMode = document.querySelector('input[name="tieMode"]:checked').value;
    const modeText = {
        'all': '全绑',
        'odd': '单数绑',
        'even': '双数绑'
    }[tieMode];

    addLog(`执行全局绑扎 - 模式: ${modeText}`, "info");
    // 这里调用实际的API
}

// 索驱控制函数
function cabinProcess() {
    addLog("启动索驱移动...", "info");
    callAPI('/api/cabin/process');
}
function cabinEmergency(status) {
    const actions = { 1: "紧急停止", 2: "暂停", 3: "恢复" };
    addLog(`执行${actions[status]}操作...`, "warning");
    callAPI('/api/cabin/emergency', 'POST', { status: status });
}

// 机械臂控制函数
function armProcess() {
    addLog("启动机械臂处理过程...", "info");
    callAPI('/api/arm/process');
}

function armEmergency(status) {
    const actions = { 1: "紧急停止", 2: "暂停", 3: "恢复" };
    addLog(`执行${actions[status]}操作...`, "warning");
    callAPI('/api/arm/emergency', 'POST', { status: status });
}


function armClearError() {
    addLog("清除机械臂错误...", "info");
    callAPI('/api/arm/clearError');
}

function armGoHome() {
    addLog("机械臂回原点...", "info");
    callAPI('/api/arm/goHome');
}


// 参数设置函数 - 打开子窗口
function openCameraParams() {
    createModal('相机参数设置', `
        <div class="param-group">
            <label>标定X偏移(mm):</label>
            <input type="number" value="0" step="0.1">
        </div>
        <div class="param-group">
            <label>标定Y偏移(mm):</label>
            <input type="number" value="0" step="0.1">
        </div>
        <div class="param-group">
            <label>标定Z偏移(mm):</label>
            <input type="number" value="0" step="0.1">
        </div>
    `);
    addLog("打开相机参数设置", "info");
}


function openCableParams() {
    createModal('索驱参数设置', `
    <div class="param-grid">
        <div class="param-group">
            <label>原点X(mm):</label>
            <input type="number" value="0" step="0.1">
        </div>
        <div class="param-group">
            <label>原点Y(mm):</label>
            <input type="number" value="0" step="0.1">
        </div>
        <div class="param-group">
            <label>作业区域x长度(mm):</label>
            <input type="number" value="100" step="0.1" min="0">
        </div>
        <div class="param-group">
            <label>作业区域y长度(mm):</label>
            <input type="number" value="100" step="0.1" min="0">
        </div>
        <div class="param-group">
            <label>x步长(mm):</label>
            <input type="number" value="10" step="0.1" min="0.1">
        </div>
        <div class="param-group">
            <label>y步长(mm):</label>
            <input type="number" value="10" step="0.1" min="0.1">
        </div>
        <div class="param-group">
            <label>索驱高度(mm):</label>
            <input type="number" value="50" step="0.1" min="0">
        </div>
        <div class="param-group">
            <label>索驱速度(mm/s):</label>
            <input type="number" value="20" step="0.1" min="0.1">
        </div>
    </div>
    `);
    addLog("打开索驱参数设置", "info");
}


async function openArmParams() {
    try {
        // 先获取数据
        const res = await callAPI("/api/arm/readCal", "GET");
        let xOffset = 0, yOffset = 0, zOffset = 0;

        if (res.code) {
            const data1 = parseResponseData(res.data);
            const cleanedData = data1.data.replace(/\\/g, '');
            const data2 = JSON.parse(cleanedData);
            xOffset = data2.X_offset || 0;
            yOffset = data2.Y_offset || 0;
            zOffset = data2.Z_offset || 0;
        }

        // 然后用获取到的数据创建模态窗口
        createModal('机械臂参数设置', `
            <div class="param-group">
                <label>标定X偏移(mm):</label>
                <input type="number" name="X_offset" value="${xOffset}" step="0.1">
            </div>
            <div class="param-group">
                <label>标定Y偏移(mm):</label>
                <input type="number" name="Y_offset" value="${yOffset}" step="0.1">
            </div>
            <div class="param-group">
                <label>标定Z偏移(mm):</label>
                <input type="number" name="Z_offset" value="${zOffset}" step="0.1">
            </div>
        `);

        addLog("打开机械臂参数设置", "info");

    } catch (error) {
        addLog("获取机械臂参数失败: " + error.message, "error");
        // 失败时使用默认值创建
        createModal('机械臂参数设置', `
            <div class="param-group">
                <label>标定X偏移(mm):</label>
                <input type="number" name="X_offset" value="0" step="0.1">
            </div>
            <div class="param-group">
                <label>标定Y偏移(mm):</label>
                <input type="number" name="Y_offset" value="0" step="0.1">
            </div>
            <div class="param-group">
                <label>标定Z偏移(mm):</label>
                <input type="number" name="Z_offset" value="0" step="0.1">
            </div>
        `);
    }
}

// 模态窗口函数
function createModal(title, content) {
    const modalContainer = document.getElementById('modal-container');

    const modal = document.createElement('div');
    modal.className = 'modal active';
    modal.innerHTML = `
        <div class="modal-content">
            <div class="modal-header">
                <h3 class="modal-title">${title}</h3>
                <button class="modal-close" onclick="closeModal(this)">&times;</button>
            </div>
            <div class="modal-body">
                ${content}
            </div>
            <div class="modal-footer">
                <button class="modal-btn secondary" onclick="closeModal(this)">取消</button>
                <button class="modal-btn primary" onclick="saveParams(this)">保存</button>
            </div>
        </div>
    `;

    modalContainer.appendChild(modal);
}

function closeModal(element) {
    const modal = element.closest('.modal');
    if (modal) {
        modal.remove();
    }
}

function saveParams(element) {
    const modal = element.closest('.modal');
    const title = modal.querySelector('.modal-title').textContent;
    if (title === '机械臂参数设置') {
        const params = {};
        modal.querySelectorAll('input').forEach(input => {
            params[input.name] = parseFloat(input.value);
        });
        callAPI("/api/arm/alertCal", "POST", params);
    }
    addLog(`${title}已保存`, "success");
    modal.remove();
}

// 日志功能
function addLog(message, type = 'info') {
    const logContainer = document.getElementById('log-container');
    const logEntry = document.createElement('div');
    logEntry.className = `log-entry ${type}`;

    const now = new Date();
    const timestamp = now.toTimeString().split(' ')[0];

    let icon = 'fa-info-circle';
    if (type === 'success') icon = 'fa-check-circle';
    else if (type === 'warning') icon = 'fa-exclamation-triangle';
    else if (type === 'error') icon = 'fa-exclamation-circle';

    logEntry.innerHTML = `
        <span class="log-time">[${timestamp}]</span>
        <i class="fas ${icon}"></i>
        <span>${message}</span>
    `;

    logContainer.appendChild(logEntry);
    logContainer.scrollTop = logContainer.scrollHeight;

    if (logContainer.children.length > 100) {
        logContainer.removeChild(logContainer.firstChild);
    }
}

function clearLogs() {
    if (confirm("确定要清除所有日志吗？")) {
        document.getElementById('log-container').innerHTML = '';
        addLog("已清除所有日志", "info");
    }
}

function exportLogs() {
    addLog("导出日志数据", "info");
    // 这里实现实际的导出功能
}

// 姿态处理
function setPose(endPointInfo) {
    document.getElementById('current-pose-x').textContent = endPointInfo.position.x.toFixed(3);
    document.getElementById('current-pose-y').textContent = endPointInfo.position.y.toFixed(3);
    document.getElementById('current-pose-z').textContent = endPointInfo.position.z.toFixed(3);
    // 姿态处理
    document.getElementById('current-pose-rx').textContent = endPointInfo.orientation.x.toFixed(3);
    document.getElementById('current-pose-ry').textContent = endPointInfo.orientation.y.toFixed(3);
    document.getElementById('current-pose-rz').textContent = endPointInfo.orientation.z.toFixed(3);
    document.getElementById('current-pose-rw').textContent = endPointInfo.orientation.w.toFixed(3);
}
// 关节数据
function updateJointsData(jointsInfo) {
    const tbody = document.getElementById('joints-tbody');
    // 清空现有内容
    tbody.innerHTML = '';

    // 遍历所有关节
    for (const [jointKey, jointData] of Object.entries(jointsInfo)) {
        const row = createJointRow(jointKey, jointData);
        tbody.appendChild(row);
    }
}
function createJointRow(jointKey, jointData) {
    const tr = document.createElement('tr');

    // 根据温度设置行样式
    if (jointData.joint_temperature > 80) {
        tr.className = 'high-temperature'; // 高温警告
    } else if (jointData.joint_temperature > 60) {
        tr.className = 'medium-temperature'; // 中温警告
    }

    // 创建表格单元格
    tr.innerHTML = `
        <td class="joint-name">
            <span class="joint-icon">🔗</span>
            ${jointData.name}
        </td>
        <td class="joint-position">${formatNumber(jointData.position, 4)}</td>
        <td class="joint-speed">${formatNumber(jointData.joint_speed, 4)}</td>
        <td class="joint-voltage">${formatNumber(jointData.joint_voltage, 2)}</td>
        <td class="joint-current">${formatNumber(jointData.joint_current, 2)}</td>
        <td class="joint-temperature">
            <span class="temp-value">${formatNumber(jointData.joint_temperature, 1)}</span>
            ${getTemperatureIcon(jointData.joint_temperature)}
        </td>
        <td class="joint-enable">
            <span class="enable-badge ${jointData.joint_en_flag ? 'enabled' : 'disabled'}">
                ${jointData.joint_en_flag ? '✅' : '❌'}
            </span>
        </td>
    `;

    return tr;
}

// 格式化数字，保留小数位数
function formatNumber(value, decimals = 2) {
    if (value === null || value === undefined) return '-';
    return Number(value).toFixed(decimals);
}

// 根据温度获取图标
function getTemperatureIcon(temperature) {
    if (temperature > 80) return '🔥';
    if (temperature > 60) return '⚠️';
    if (temperature > 40) return '🌡️';
    return '❄️';
}

// 图像展示
function setComparisonImage(base64String, imageType = 1) {
    const imageId = `comparison-img-${imageType}`;
    const placeholderId = `placeholder-comparison-${imageType}`;
    const containerId = `comparison-image-${imageType}`;

    const imageElement = document.getElementById(imageId);
    const placeholderElement = document.getElementById(placeholderId);
    const containerElement = document.getElementById(containerId);

    if (!imageElement || !placeholderElement) {
        console.error('找不到图像元素:', imageId);
        return;
    }

    // 添加加载状态
    if (containerElement) {
        containerElement.classList.add('loading');
    }

    const dataUrl = `data:image/jpeg;base64,${base64String}`;

    const img = new Image();
    img.onload = function () {
        imageElement.src = dataUrl;
        imageElement.style.display = 'block';
        placeholderElement.style.display = 'none';

        // 移除加载状态
        if (containerElement) {
            containerElement.classList.remove('loading');
        }
    };

    img.onerror = function () {
        placeholderElement.innerHTML = `
            <i class="fas fa-exclamation-triangle"></i>
            <p>图像加载失败</p>
            <small>请检查图像数据格式</small>
        `;

        if (containerElement) {
            containerElement.classList.remove('loading');
        }
    };

    img.src = dataUrl;
}

// 全局存储最新点位数据，供表格渲染和筛选使用
let globalDetectPoints = [];

// 处理detect_points事件
// 更新检测到的点位数据
function updateDetectPoints(data) {
    // 1. 预处理数据：过滤掉null元素，添加必要字段（如点位ID、默认移动状态）
    const processedPoints = data.detect
        .filter(point => point !== null) // 移除数组中的null元素
        .map((point, index) => {
            // 补充默认字段：如果后端未返回is_rebar/is_useful/move_status，设置默认值
            return {
                idx: point.idxName, // 点位唯一ID（表格展示用）
                Pix_coord: [point.Pix_coordX, point.Pix_coordY], // 像素坐标数组（适配原渲染逻辑）
                World_coord: [point.World_coordX, point.World_coordY, point.World_coordZ || 0], // 世界坐标（Z轴默认0）
                Angle: point.Angle, // 角度
                is_rebar: point.is_rebar,
                is_useful: point.is_useful,
                move_status: "pending" // 初始移动状态：未移动
            };
        });

    // 2. 更新全局点位数据，供后续渲染和筛选使用
    globalDetectPoints = [...processedPoints, ...globalDetectPoints];

    // 3. 渲染表格：调用之前的renderPointData函数，传入处理后的数据
    renderPointData(globalDetectPoints);

    // 4. 记录系统日志：告知用户点位更新情况
    addLog(`成功接收 ${processedPoints.length} 个点位数据`, "success");
    const prePoints = data.detect
        .filter(point => point !== null) // 移除数组中的null元素
        .map((point, index) => {
            // 补充默认字段：如果后端未返回is_rebar/is_useful/move_status，设置默认值
            return {
                idx: point.idxName, // 点位唯一ID（表格展示用）
                World_coord: [point.World_coordX, point.World_coordY, point.World_coordZ || 0], // 世界坐标（Z轴默认0）
            };
        });
    recordDetectionEvent("点位更新," + "共: " + processedPoints.length + "个", data.detect, prePoints);

    // （可选）5. 若有实时筛选状态，重新触发筛选，确保表格显示符合当前筛选条件
    filterTable();
}

function eventMovePoint(data) {
    // 更新表格状态
    updateTableRowStatus(data.pointCoord.idxName, 'moving');
    const prePoints = {
        idx: data.pointCoord.idxName, // 点位唯一ID（表格展示用）
        World_coord: [data.pointCoord.World_coordX, data.pointCoord.World_coordY, data.pointCoord.World_coordZ || 0], // 世界坐标（Z轴默认0）
    }
    recordMoveEvent("id:" + data.pointCoord.idxName, data, prePoints);

}

// 更新表格行状态的函数
function updateTableRowStatus(pointId, status) {
    const rows = document.querySelectorAll('#point-data-body .point-row');

    // 1. 更新 globalDetectPoints 中的数据
    globalDetectPoints = globalDetectPoints.map(point => {
        if (point.idx === pointId) {
            return {
                ...point,
                move_status: status
            };
        }
        return point;
    });

    rows.forEach(row => {
        const idxCell = row.cells[0]; // 第一列是ID
        if (idxCell.textContent === pointId) {
            // 更新状态列（最后一列）
            const statusCell = row.cells[6]; // 第七列是状态
            statusCell.innerHTML = getStatusBadge(status);

            // 添加动画效果
            row.style.animation = 'pulse 0.5s ease-in-out';
            setTimeout(() => {
                row.style.animation = '';
            }, 500);
        }
    });
    // 更新统计数字
    updateStatistics();
}

// 新增：专门更新统计数字的函数
function updateStatistics() {
    const rows = document.querySelectorAll('#point-data-body .point-row');
    let successCount = 0;
    let failedCount = 0;
    let pendingCount = 0;

    rows.forEach(row => {
        const statusCell = row.cells[6];
        const statusText = statusCell.textContent.trim();

        if (statusText === '成功') successCount++;
        else if (statusText === '失败' || statusText === '不可用') failedCount++;
        else pendingCount++; // 包括"等待中"和"移动中"
    });

    const totalCount = rows.length;

    // 更新统计显示
    document.getElementById('total-points').textContent = totalCount;
    document.getElementById('success-points').textContent = successCount;
    document.getElementById('failed-points').textContent = failedCount;
    document.getElementById('pending-points').textContent = pendingCount;
}

// 状态标签生成函数
function getStatusBadge(status, isUseful = true) {
    if (!isUseful) return `<span class="boolean-tag tag-unuseful">不可用</span>`;
    const statusConfig = {
        'pending': { text: '等待中', class: 'tag-pending' },
        'moving': { text: '移动中', class: 'tag-moving' },
        'success': { text: '成功', class: 'tag-success' },
        'failed': { text: '失败', class: 'tag-failed' }
    };
    const config = statusConfig[status] || statusConfig.pending;
    return `<span class="boolean-tag ${config.class}">${config.text}</span>`;
}

function eventMoveInfo(data) {
    if (!data.isSuccess) {
        addLog(data.idxName + "执行失败", "failed");
        updateTableRowStatus(data.idxName, 'failed');
    } else if (data.isOver) {
        // 所有阶段都成功完成
        addLog(data.idxName + "所有阶段执行成功", "success");
        updateTableRowStatus(data.idxName, 'success');
    }
    let prePoints = {
        idx: data.idxName
    };
    // 动态添加所有state的message
    Object.keys(data.state).forEach(stateKey => {
        prePoints[`${stateKey}_message`] = data.state[stateKey].message;
    });
    if (!data.isSuccess) {
        recordErrorEvent("id:" + data.idxName, data, prePoints);
    } else {
        recordMoveEvent("id:" + data.idxName, data, prePoints);
    }
}

function eventStopInfo(data) {
    recordErrorEvent("错误信息", data);
}

// 处理实时数据
function realtimeCallback(data) {
    if (!data) return;
    // 位置处理
    setPose(JSON.parse(data.data.endPointInfo));
    // 修改关节数据
    updateJointsData(data.data.jointsInfo);
    // 图像展示
    if (data.data.imgShowInfo) {
        setComparisonImage(data.data.imgShowInfo, 1);
        setComparisonImage(data.data.imgShowInfo, 2);
    }
}
// 处理事件数据
function eventCallback(data) {
    if (data.type == "detect_points") {
        updateDetectPoints(data.data);
    }
    else if (data.type == "move_point") {
        eventMovePoint(data.data);
    }
    else if (data.type == "move_info") {
        eventMoveInfo(data.data);
    }
    else if (data.type == "stop_info") {
        eventStopInfo(data.data);
    }
}

// 初始化WebSocket连接
function initWebSocket() {
    try {
        const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
        const host = window.location.hostname || '10.0.0.7';
        const port = window.location.port || '7722';
        const wsUrl = `${protocol}//${host}:${port}`;

        console.log('🔌 连接WebSocket:', wsUrl);
        socket = io(wsUrl, {
            transports: ['websocket', 'polling']
        });

        // 连接状态监听
        socket.on('connect', function () {
            console.log('✅ WebSocket连接成功');
            addLog("WebSocket连接已建立", "success");
            useRealData = true;
            isUsingRealData = true;
        });

        socket.on('disconnect', function () {
            console.log('❌ WebSocket连接断开');
            addLog("WebSocket连接已断开", "warning");
            useRealData = false;
            isUsingRealData = false;

        });

        socket.on('connect_error', function (error) {
            console.error('💥 WebSocket连接错误:', error);
            addLog("WebSocket连接错误: " + error.message, "error");
            useRealData = false;
        });

        // 统一的数据接收处理
        socket.on('message', function (data) {
            console.log('📨 收到WebSocket消息:', data);
            try {
                const parsedData = typeof data === 'string' ? JSON.parse(data) : data;
                handleWebSocketMessage(parsedData);
            } catch (error) {
                console.error('消息解析错误:', error);
                addLog("WebSocket消息解析错误", "error");
            }
        });

        // 专门的事件数据通道
        socket.on('ros_event_data', function (data) {
            console.log('📢 收到ROS事件数据:', data);
            eventCallback(data);
        });

        // 实时数据通道
        socket.on('ros_realtime_data', function (data) {
            realtimeCallback(data);
        });

        // 状态数据通道
        socket.on('ros_status_data', function (data) {
            console.log('📈 收到状态数据:', data);
        });

    } catch (error) {
        console.error('WebSocket初始化失败:', error);
        addLog("WebSocket初始化失败: " + error.message, "error");
    }
}



// API调用函数
async function callAPI(endpoint, method = 'GET', data = null) {
    const options = {
        method: method,
        headers: {
            'Content-Type': 'application/json',
        },
    };

    const host = window.location.hostname || '10.0.0.7';
    const port = window.location.port || '7722';
    const url = `http://${host}:${port}${endpoint}`;

    if (data) options.body = JSON.stringify(data);

    // ✅ 设置 3 分钟超时
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), 3 * 60 * 1000); // 3分钟
    options.signal = controller.signal;

    addLog(`调用API: ${method} ${url}`, 'info');

    try {
        const resp = await fetch(url, options);
        clearTimeout(timeoutId); // 清除超时
        if (!resp.ok) {
            throw new Error(`HTTP ${resp.status} ${resp.statusText}`);
        }
        const result = await resp.json();
        addLog(`API调用成功: ${result.message}`, 'success');
        return result;
    } catch (err) {
        if (err.name === 'AbortError') {
            addLog(`API调用超时（3分钟）`, 'error');
            throw new Error('API调用超时（3分钟）');
        } else {
            addLog(`API调用失败: ${err.message}`, 'error');
            throw err;
        }
    }
}

// 3. 渲染点位表格
function renderPointData(points) {
    const tableBody = document.getElementById('point-data-body');
    // 统计元素
    const totalEl = document.getElementById('total-points');
    const successEl = document.getElementById('success-points');
    const failedEl = document.getElementById('failed-points');
    const pendingEl = document.getElementById('pending-points');
    // 初始化统计计数
    let totalCount = 0;
    if (points != null)
        totalCount = points.length;
    // 清空表格
    tableBody.innerHTML = '';
    // 无数据时显示提示
    if (totalCount === 0) {
        tableBody.innerHTML = `
            <tr>
                <td colspan="7" 
                    style="padding: 30px; text-align: center; color: var(--text-muted); font-size: 14px; background: rgba(30,41,59,0.2);">
                    <i class="fas fa-info-circle" style="margin-right: 8px; color: var(--accent-blue);"></i> 未识别到有效点位
                </td>
            </tr>
        `;
        return;
    }
    let successCount = 0;
    let failedCount = 0;
    let pendingCount = 0;

    // 计算各状态数量
    points.forEach(point => {
        if (point.move_status === 'success') successCount++;
        else if (point.move_status === 'failed') failedCount++;
        else pendingCount++;
    });
    // 更新统计数据显示
    totalEl.textContent = totalCount;
    successEl.textContent = successCount;
    failedEl.textContent = failedCount;
    pendingEl.textContent = pendingCount;

    // 循环渲染每个点位
    points.forEach(point => {
        const row = document.createElement('tr');
        row.style.backgroundColor = points.indexOf(point) % 2 === 0
            ? 'rgba(30,41,59,0.2)'
            : 'rgba(30,41,59,0.4)';
        row.style.transition = 'all 0.2s ease';
        row.className = 'point-row';

        // 类型标签：根据is_rebar判断
        const typeTag = point.is_rebar
            ? `<span class="boolean-tag tag-true">钢筋</span>`
            : `<span class="boolean-tag tag-other">其他</span>`;
        // 可用状态标签：根据is_useful判断
        const usefulTag = point.is_useful
            ? `<span class="boolean-tag tag-useful">可用</span>`
            : `<span class="boolean-tag tag-unuseful">不可用</span>`;
        const isUseful = point.is_rebar && point.is_useful;
        // 填充表格单元格
        row.innerHTML = `
            <td style="padding: 12px 10px; text-align: center; color: var(--text-secondary); font-size: 13px; border-right: 1px solid rgba(71,85,101,0.2); border-bottom: 1px solid rgba(71,85,101,0.2);">${point.idx}</td>
            <td style="padding: 12px 10px; text-align: center; color: var(--text-secondary); font-size: 13px; border-right: 1px solid rgba(71,85,101,0.2); border-bottom: 1px solid rgba(71,85,101,0.2);">(${point.Pix_coord[0]}, ${point.Pix_coord[1]})</td>
            <td style="padding: 12px 10px; text-align: center; color: var(--text-secondary); font-size: 13px; border-right: 1px solid rgba(71,85,101,0.2); border-bottom: 1px solid rgba(71,85,101,0.2);">(${point.World_coord[0].toFixed(3)}, ${point.World_coord[1].toFixed(3)}, ${point.World_coord[2].toFixed(3)})</td>
            <td style="padding: 12px 10px; text-align: center; color: var(--text-secondary); font-size: 13px; border-right: 1px solid rgba(71,85,101,0.2); border-bottom: 1px solid rgba(71,85,101,0.2);">${point.Angle.toFixed(1)}</td>
            <td style="padding: 12px 10px; text-align: center; color: var(--text-secondary); font-size: 13px; border-right: 1px solid rgba(71,85,101,0.2); border-bottom: 1px solid rgba(71,85,101,0.2);">${typeTag}</td>
            <td style="padding: 12px 10px; text-align: center; color: var(--text-secondary); font-size: 13px; border-right: 1px solid rgba(71,85,101,0.2); border-bottom: 1px solid rgba(71,85,101,0.2);">${usefulTag}</td>
            <td style="padding: 12px 10px; text-align: center; color: var(--text-secondary); font-size: 13px; border-bottom: 1px solid rgba(71,85,101,0.2);">
                    ${getStatusBadge(point.move_status || 'pending', isUseful)}  <!-- 添加这一行 -->
            </td>
        `;

        tableBody.appendChild(row);
    });

}

// 6. 搜索与筛选功能（核心功能，与参考案例对齐）
function filterTable() {
    // 获取筛选条件
    const searchTerm = document.querySelector('.search-box').value.toLowerCase().trim();
    const typeFilter = document.getElementById('type-filter').value;

    // 获取所有点位行
    const rows = document.querySelectorAll('.point-row');
    rows.forEach(row => {
        // 获取当前行的关键数据
        const pointId = row.cells[0].textContent.toLowerCase(); // 点位ID
        const coords = row.cells[1].textContent.toLowerCase() + row.cells[2].textContent.toLowerCase(); // 坐标
        const typeText = row.cells[4].textContent.toLowerCase(); // 类型（钢筋/其他）

        // 匹配筛选条件
        const matchesSearch = pointId.includes(searchTerm) || coords.includes(searchTerm);
        const matchesType = typeFilter === 'all' ||
            (typeFilter === 'rebar' && typeText.includes('钢筋')) ||
            (typeFilter === 'other' && typeText.includes('其他'));

        // 显示或隐藏行
        row.style.display = (matchesSearch && matchesStatus && matchesType) ? '' : 'none';
    });
}

// 7. 初始化搜索与筛选事件监听
function initFilterEvents() {
    // 搜索框输入事件
    document.querySelector('.search-box').addEventListener('input', filterTable);
    // 类型筛选下拉框变化事件
    document.getElementById('type-filter').addEventListener('change', filterTable);
}


// 9. 新增配套样式（添加到 styles.css 末尾）
const filterStyle = document.createElement('style');
filterStyle.textContent = `
    /* 筛选控件样式补充 */
    .search-box:focus, .filter-select:focus {
        border-color: var(--accent-blue);
        box-shadow: 0 0 0 2px rgba(98, 111, 246, 0.2);
    }

    /* 状态指示器样式 */
    .status-indicator {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        width: 24px;
        height: 24px;
        border-radius: 50%;
        font-size: 14px;
        color: white;
    }
    .status-success {
        background-color: var(--accent-green);
        box-shadow: 0 0 8px rgba(16, 185, 129, 0.4);
    }
    .status-failed {
        background-color: var(--accent-red);
        box-shadow: 0 0 8px rgba(239, 68, 68, 0.4);
    }
    .status-pending {
        background-color: var(--accent-orange);
        box-shadow: 0 0 8px rgba(245, 158, 11, 0.4);
    }

    /* 标签样式 */
    .boolean-tag {
        display: inline-block;
        padding: 5px 10px;
        border-radius: 6px;
        font-size: 12px;
        font-weight: 600;
        transition: all 0.2s ease;
    }
    .tag-true {
        background-color: rgba(16, 185, 129, 0.2);
        color: var(--accent-green);
    }
    .tag-other {
        background-color: rgba(59, 130, 246, 0.2);
        color: var(--accent-blue);
    }
    .tag-useful {
        background-color: rgba(16, 185, 129, 0.2);
        color: var(--accent-green);
    }
    .tag-unuseful {
        background-color: rgba(239, 68, 68, 0.2);
        color: var(--accent-red);
    }
`;
document.head.appendChild(filterStyle);



// 移动事件记录
function recordMoveEvent(message, data = null, predata = null) {
    window.eventsManager.addEvent('move', message, data, predata);
}

// 检测事件记录  
function recordDetectionEvent(message, data = null, predata = null) {
    window.eventsManager.addEvent('detection', message, data, predata);
}

// 错误事件记录
function recordErrorEvent(message, data = null, predata = null) {
    window.eventsManager.addEvent('error', message, data, predata);
}

// 清除事件函数
function clearEvents() {
    window.eventsManager.clearEvents('all');
}

function clearMoveEvents() {
    window.eventsManager.clearEvents('move');
}

function clearDetectionEvents() {
    window.eventsManager.clearEvents('detection');
}

function clearErrorEvents() {
    window.eventsManager.clearEvents('error');
}

// 导出事件函数
function exportEvents() {
    window.eventsManager.exportEvents('all');
}

function exportMoveEvents() {
    window.eventsManager.exportEvents('move');
}

function exportDetectionEvents() {
    window.eventsManager.exportEvents('detection');
}

function exportErrorEvents() {
    window.eventsManager.exportEvents('error');
}



// 解析字符串数据
function parseResponseData(dataString) {
    const result = {};

    // 按行分割
    const lines = dataString.split('\n').filter(line => line.trim());

    lines.forEach(line => {
        // 找到第一个冒号的位置
        const colonIndex = line.indexOf(':');
        if (colonIndex > 0) {
            const key = line.substring(0, colonIndex).trim();
            let value = line.substring(colonIndex + 1).trim();

            // console.log(`解析: key=${key}, value=${value}`);

            // 处理布尔值
            if (value === 'True') {
                result[key] = true;
            } else if (value === 'False') {
                result[key] = false;
            }
            // 处理带引号的字符串（保留完整的字符串内容）
            else if (value.startsWith('"') && value.endsWith('"')) {
                // 移除首尾引号，但保持内部转义字符
                result[key] = value.slice(1, -1);
            }
            // 其他情况直接赋值
            else {
                result[key] = value;
            }
        }
    });

    return result;
}